简述
陆陆续续看spring IoC与AOP大概一个多月,今天整理下笔记,方便以后的复习。
只要是做Java web的基本都很熟悉spring,提到spring,必说其核心的两个概念:IoC与AOP,实际只要看过源码的小伙伴,肯定知道spring的AOP是基于IoC做的,而且spring的AOP也只能处理自己管理的bean,针对的是方法级的切面。
IoC
谈到IoC(Inversion of Control),”控制反转“,面向对象的设计思想之一。
解决的问题:利用依赖注入的方式,实现对象之间的解耦。
了解IoC,我们从几个方面进行剖析:
- 为什么引入IoC
- spring如何实现的IoC
- Bean的解析,注册
- Bean的实例化
为什么引入IoC
什么是IoC
控制反转,是面向对象的一种设计原则,减少代码之间的耦合,还有另外一种叫法”依赖注入DI“。
使用IoC的前后差别
IoC提供的策略:你要的时候,我给你送来。
控制反转遵循好莱坞原则:Don’t call us, we will call you.
IoC解决什么问题
1.业务对象的构建管理
2.业务对象间的依赖绑定
IoC的实现原理
简单一句话总结:通过Java反射,即set赋值
spring如何实现IoC
最核心:Bean
理解bean,必须理解三个核心接口:
BeanFactory
IoC容器的接口定义。
IoC比作水桶,那BeanFactory就是定义水桶的基本功能,能装水,有把手。
ApplicationContext
BeanFactory是最基本的水桶,而ApplicationContext是扩展后的水桶,它通过继承 MessageSource,ResourceLoader,ApplicationEventPublisher 接口,在BeanFactory 简单IOC容器的基础上添加了许多对高级容器的支持。
BeanDefinition
实现控制反转的核心数据结构。每个bean都有自己的信息,各个属性,类名,类型,是否单例,这些都是bean的信息。
题外话
陆续看一些redis,mysql核心原理都在于对模型的抽象,即数据结构。
大家可以打开spring的源码重点看下这三个接口,对他们有个大概的了解,因为后续的源码解析,会用到这三个。
Bean的解析与注册
通过一个简单的入口进行核心流程。
配置条件:简单的bean,spring配置的xml,启动类
Person1
2
3
4
5
6public class Person {
private String name;
private String age;
}
spring.xml1
2
3
4
5
6
7
8
9
10
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="person" class="com.xx.Person">
<property name="age" value="yy"/>
<property name="name" value="xx"/>
</bean>
</beans>
启动类1
2
3
4public static void main(String[] args) {
ApplicationContext ctx = new FileSystemXmlApplicationContext("classpath:spring.xml");
((Person) ctx.getBean("person"));
}
一切就绪,准备开始进行spring源码的核心:
AbstractApplicationContext
1 | /** |
xml bean的解析及注册就在obtaionFreshBeanFactory();
1 |
|
然后交给了AbstractXmlApplicationContext
1 |
|
然后交给了 XmlBeanDefinitionReader进行bean的解析。真正的解析方法。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 解析成Document
Document doc = doLoadDocument(inputSource, resource);
// 从Document 解析bean,然后注册
return registerBeanDefinitions(doc, resource);
}
catch (BeanDefinitionStoreException ex) {
throw ex;
}
catch (SAXParseException ex) {
...
}
}
从registerBeanDefinitions跳到DefaultBeanDefinitionDocumentReader
核心逻辑在parseBeanDefinitions(root, this.delegate)
1 | protected void doRegisterBeanDefinitions(Element root) { |
然后执行parseDefaultElement(ele, delgate),大家可以看到熟悉的bean标签解析
1 | private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { |
在processBeanDefinition()方法
首先创建一个BeanDefinitionHolder调用BeanDefinitionReaderUtils.registerBeanDefinition方法
1 | protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { |
那beanDefinition是什么时候创建的呢?
在delegate.parseBeanDefinitionElement()里的parseBeanDefinitionElement()
1 | public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { |
到这一步,bean工厂创建完成,但并未实例化。
bean的实例化
实例化过程图

源码分析就是三步
1.实例化bean(BeanUtils.instantiateClass(constructorToUse))
2.设置属性包括依赖及设值 (populateBean(…))
3.扩展的aware及前置,初始化方法(afterPropertiesSet 、 init-method),后置
还记的refresh()的那条语句嘛?1
2// 实例化所有的(non-lazy-init)单例
finishBeanFactoryInitialization(beanFactory);
1.实例化doGetBean()1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52public Object getBean(String name) throws BeansException {
return doGetBean(name, null, null, false);
}
public Object instantiate(RootBeanDefinition bd, String beanName, BeanFactory owner) {
// Don't override the class with CGLIB if no overrides.
if (bd.getMethodOverrides().isEmpty()) {
Constructor<?> constructorToUse;
synchronized (bd.constructorArgumentLock) {
constructorToUse = (Constructor<?>) bd.resolvedConstructorOrFactoryMethod;
if (constructorToUse == null) {
final Class<?> clazz = bd.getBeanClass();
if (clazz.isInterface()) {
throw new BeanInstantiationException(clazz, "Specified class is an interface");
}
try {
if (System.getSecurityManager() != null) {
constructorToUse = AccessController.doPrivileged(new PrivilegedExceptionAction<Constructor<?>>() {
public Constructor<?> run() throws Exception {
return clazz.getDeclaredConstructor((Class[]) null);
}
});
}
else {
constructorToUse = clazz.getDeclaredConstructor((Class[]) null);
}
bd.resolvedConstructorOrFactoryMethod = constructorToUse;
}
catch (Throwable ex) {
throw new BeanInstantiationException(clazz, "No default constructor found", ex);
}
}
}
// 核心点
return BeanUtils.instantiateClass(constructorToUse);
}
else {
// Must generate CGLIB subclass.
return instantiateWithMethodInjection(bd, beanName, owner);
}
}
public static <T> T instantiateClass(Constructor<T> ctor, Object... args) throws BeanInstantiationException {
Assert.notNull(ctor, "Constructor must not be null");
try {
ReflectionUtils.makeAccessible(ctor);
return ctor.newInstance(args);
}
...
}
2.属性装载
1 | protected void populateBean(String beanName, RootBeanDefinition mbd, BeanWrapper bw) { |
3.扩展的处理1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41/**
* @see BeanNameAware
* @see BeanClassLoaderAware
* @see BeanFactoryAware
* @see #applyBeanPostProcessorsBeforeInitialization
* @see #invokeInitMethods
* @see #applyBeanPostProcessorsAfterInitialization
*/
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
if (System.getSecurityManager() != null) {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
invokeAwareMethods(beanName, bean);
return null;
}
}, getAccessControlContext());
}
else {
invokeAwareMethods(beanName, bean);
}
Object wrappedBean = bean;
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}
catch (Throwable ex) {
throw new BeanCreationException(
(mbd != null ? mbd.getResourceDescription() : null),
beanName, "Invocation of init method failed", ex);
}
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
return wrappedBean;
}
到此bean的实例化结束。
IoC整个过程完毕:解析,注册,实例化。
总结
通过一个简单的demo,从xml的解析bean并注册,以及最后的实例化。可以看到spring的封装。光解析就分了好多种,例如:DocumentDefinitionReader,XmlDefinitionReader,etc良好的设计代表了优秀的扩展力。实际解析最重要的核心就是BeanDefinition的构建,解析完注册到工厂,实例化就是通过反射进行实例化,并通过beanDefinition的PropertyValues进行实例的注入(BeanFactory.getBean()),完成了整个流程,而且在实例化最后还进行扩展接口的调用,为后续开发者使用spring实现bean其他功能进行扩展。
IoC容器的大致流程:
资源的定位
bean的解析,BeanFactory的构建,以及bean的注册
bean的实例化
如果有兴趣,也可以反着来,直接写个Person的构造,然后把断点打在上面,看下整个程序的调用栈。

参考文献
Spring IOC 容器源码分析
深入理解 Spring 之源码剖析IOC
Spring源码深度解析(第2版)
Spring揭秘